#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>


#include "led_opr.h"

#define LED_NUM 2

static int major = 0;
static struct class *imx6_led_class;
struct led_operations *p_led_opr;


static ssize_t imx6_led_open(struct inode *inode, struct file *file)
{
	/*根据次设备号来初始化LED*/

	int minor = iminor(inode); /*iminor宏定义用于获取次设备号，通过struct inode*/
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	p_led_opr->init(minor);
	
	return 0;
}

static ssize_t imx6_led_release(struct inode *inode, struct file *file)
{
	return 0;
}

static ssize_t imx6_led_write(struct file *file, const char  __user *buf, size_t size, loff_t *offset)
{
	/*根据次设备号和status来控制LED*/
	int err;
	char status;
	
	struct inode *inode = file_inode(file); /*writer 函数传递的原始参数无inode结构体，要进行转换*/
	int minor = iminor(inode);

	err = copy_from_user(&status, buf, 1); 
	
	p_led_opr->ctl(minor,status);

	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	
	return 1;
}

struct file_operations imx6_led_fops = {
	.owner		= THIS_MODULE,
	.open		= imx6_led_open,
	.write		= imx6_led_write,
	.release	= imx6_led_release
};

static int __init imx6_led_init(void)
{
	int i;
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	major = register_chrdev(0, "imx6_led", &imx6_led_fops);

	imx6_led_class = class_create(THIS_MODULE, "imx6_led_class");  /*在sysfs下创建一个类*/

	if(IS_ERR(imx6_led_class)){
		unregister_chrdev(major,"imx6_led");
		return -1;
	}

	for(i = 0; i < LED_NUM; i++)
		device_create(imx6_led_class, NULL, MKDEV(major, i), NULL, "imx6_led%d",i); /*  /dev/imx6_led0,1...  */

	p_led_opr = get_board_led_opr();
	
	return 0;
}

static void __exit imx6_led_exit(void)
{
	int i;
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	for(i = 0; i < LED_NUM; i++)
		device_destroy(imx6_led_class, MKDEV(major, i));
	
	class_destroy(imx6_led_class);
	unregister_chrdev(major,"imx6_led");
}

module_init(imx6_led_init);
module_exit(imx6_led_exit);
MODULE_LICENSE("GPL");


